#!/usr/bin/env python
# -*- Mode: Python; tab-width: 4 -*-
#
# Parser for ClamAV mirrros.dat files
#
# Copyright (C) 2008 Gianluigi Tiesi <sherpya@netfarm.it>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
# ======================================================================

from struct import pack, unpack
from time import ctime

__all__ = [ 'entry_size', 'parse_entry', 'print_entry', 'create_entry', 'gen_list' ]

entry_size = 0x34 # 52

def parse_entry(entry):
    entry = entry[:-32]
    a, b, c, d = unpack('BBBB', entry[:4])
    entry = entry[4:]
    atime, succ, fail = unpack('<III', entry[:12])
    entry = entry[12:]
    ignore = unpack('Bxxx', entry)[0] and True or False
    ip = '%d.%d.%d.%d' % (a, b, c, d)
    return dict(ip=ip, atime=atime, succ=succ, fail=fail, ignore=ignore)

def print_entry(entry_s):
    print
    print 'ip:', entry_s['ip']
    print 'last access:', ctime(entry_s['atime'])
    print 'successes:', entry_s['succ']
    print 'failures:', entry_s['fail']
    print 'ignore:', entry_s['ignore']

def create_entry(entry_s):
    # ip
    bin = ''.join(map(lambda x: chr(int(x)), entry_s['ip'].split('.')))
    # atime, succ and fail
    bin = bin + pack('<III', entry_s['atime'], entry_s['succ'], entry_s['fail'])
    # ignore
    bin = bin + (entry_s['ignore'] and chr(1) or chr(0))
    # padding, please note last 3 bytes are random data from freshclam mem
    bin = bin + (chr(0xff) * (3 + 32))
    return bin

def gen_list(data):
    mirrors = []
    while len(data) > 0:
        entry = data[:entry_size]
        if len(entry) != entry_size: break
        data = data[entry_size:]
        mirrors.append(parse_entry(entry))
    return mirrors

if __name__ == '__main__':
    data = open('mirrors.dat', 'rb').read()

    for mirror in gen_list(data):
        print_entry(parse_entry(create_entry(mirror)))
